home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Views / Sources / UTECommands.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  49.3 KB  |  1,681 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UTECommands.cp
  3. // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UTECOMMANDS__
  7. #include "UTECommands.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. //    #ifndef __UAPPLICATION__
  13. //    #include "UApplication.h"
  14. //    #endif
  15.  
  16. #ifndef __UCLIPBOARDMGR__
  17. #include "UClipboardMgr.h"
  18. #endif
  19.  
  20. #ifndef __UDIALOG__
  21. #include "UDialog.h"
  22. #endif
  23.  
  24. #ifndef __UDOCUMENT__
  25. #include "UDocument.h"
  26. #endif
  27.  
  28. #ifndef __UERRORMGR__
  29. #include "UErrorMgr.h"
  30. #endif
  31.  
  32. #ifndef __UFAILURE__
  33. #include "UFailure.h"
  34. #endif
  35.  
  36. #ifndef __UFILE__
  37. #include "UFile.h"
  38. #endif
  39.  
  40. #ifndef __UGEOMETRY__
  41. #include "UGeometry.h"
  42. #endif
  43.  
  44. #ifndef __ULIST__
  45. #include "UList.h"
  46. #endif
  47.  
  48. #ifndef __UMACAPPGLOBALS__
  49. #include "UMacAppGlobals.h"
  50. #endif
  51.  
  52. #ifndef __UMACAPPUTILITIES__
  53. #include "UMacAppUtilities.h"
  54. #endif
  55.  
  56. #ifndef __UMEMORY__
  57. #include "UMemory.h"
  58. #endif
  59.  
  60. #ifndef __UMENUMGR__
  61. #include "UMenuMgr.h"
  62. #endif
  63.  
  64. #ifndef __UPATCH__
  65. #include "UPatch.h"
  66. #endif
  67.  
  68. #ifndef __UPRINTHANDLER__
  69. #include "UPrintHandler.h"
  70. #endif
  71.  
  72. #ifndef __USCROLLER__
  73. #include "UScroller.h"
  74. #endif
  75.  
  76. #ifndef __UWINDOW__
  77. #include "UWindow.h"
  78. #endif
  79.  
  80. // Toolbox
  81.  
  82. #ifndef __ALIASES__
  83. #include <Aliases.h>
  84. #endif
  85.  
  86. #ifndef __DIALOGS__
  87. #include <Dialogs.h>
  88. #endif
  89.  
  90. #ifndef __EDITIONS__
  91. #include <Editions.h>
  92. #endif
  93.  
  94. #ifndef __ERRORS__
  95. #include <Errors.h>
  96. #endif
  97.  
  98. #ifndef __FONTS__
  99. #include <Fonts.h>
  100. #endif
  101.  
  102. #ifndef __GESTALTEQU__
  103. #include <GestaltEqu.h>
  104. #endif
  105.  
  106. #ifndef __MENUS__
  107. #include <Menus.h>
  108. #endif
  109.  
  110. #ifndef __PACKAGES__
  111. #include <Packages.h>
  112. #endif
  113.  
  114. #ifndef __SCRAP__
  115. #include <Scrap.h>
  116. #endif
  117.  
  118. #ifndef __SCRIPT__
  119. #include <Script.h>
  120. #endif
  121.  
  122. #ifndef __TOOLUTILS__
  123. #include <ToolUtils.h>
  124. #endif
  125.  
  126. // ANSI
  127.  
  128. #ifndef __STDIO__
  129. #include <stdio.h>
  130. #endif
  131.  
  132.  
  133. //========================================================================================
  134. // GLOBAL Procedures
  135. //========================================================================================
  136. #undef Inherited
  137.  
  138. #if qDebug
  139.  
  140. //----------------------------------------------------------------------------------------
  141. // DumpTTECommand: 
  142. //----------------------------------------------------------------------------------------
  143. #pragma segment TEDebug
  144.  
  145. void DumpTTECommand(TTECommand* theTTECommand)
  146. {
  147.     long oldStyleSize;
  148.     long newStyleSize;
  149.     long last;
  150.  
  151.     long oldDiff = Max(theTTECommand->fOldEnd - theTTECommand->fOldStart, 0);
  152.     long newDiff = Max(theTTECommand->fNewEnd - theTTECommand->fNewStart, 0);
  153.  
  154.     fprintf(stderr, "old start/end, new start/end, diff :%1d/%1d,  %1d/%1d,  %1d \n", theTTECommand->fOldStart, theTTECommand->fOldEnd, theTTECommand->fNewStart, theTTECommand->fNewEnd, Max(oldDiff, newDiff));
  155.     fprintf(stderr, "fTextPad :%1d\n", theTTECommand->fTextPad);
  156.     fprintf(stderr, "fPadding size :%1d\n", GetHandleSize(theTTECommand->fPadding));
  157.  
  158.     oldStyleSize = 0;
  159.     newStyleSize = 0;
  160.     fprintf(stderr, "** Old styles:\n");
  161.     if (theTTECommand->fOldStyles == NULL)
  162.         fprintf(stderr, "NONE!\n");
  163.     else
  164.     {
  165.  
  166.         last = (*theTTECommand->fOldStyles)->scrpNStyles;
  167.         fprintf(stderr, "Number of table entries: %1d\n", last);
  168.         for (long i = 0; i <= last - 1; ++i)
  169.         {
  170.             ScrpSTElement & theScrpSTElement = (*theTTECommand->fOldStyles)->scrpStyleTab[i];
  171.  
  172.             fprintf(stderr, "%1d, ofs:%1d ", theScrpSTElement.scrpStartChar);
  173.             fprintf(stderr, "\n");
  174.         }
  175.         oldStyleSize = GetHandleSize((Handle)(theTTECommand->fOldStyles));
  176.     }
  177.  
  178.     fprintf(stderr, "** New styles:\n");
  179.     if (theTTECommand->fNewStyles == NULL)
  180.         fprintf(stderr, "NONE!\n");
  181.     else
  182.     {
  183.         last = (*theTTECommand->fNewStyles)->scrpNStyles;
  184.         fprintf(stderr, "Number of table entries: %1d\n", last);
  185.         for (long i = 0; i <= last - 1; ++i)
  186.         {
  187.             ScrpSTElement & theScrpSTElement = (*theTTECommand->fNewStyles)->scrpStyleTab[i];
  188.  
  189.             fprintf(stderr, "%1d, ofs:%1d ", theScrpSTElement.scrpStartChar);
  190.             fprintf(stderr, "\n");
  191.         }
  192.         newStyleSize = GetHandleSize((Handle)(theTTECommand->fNewStyles));
  193.     }
  194.  
  195.     fprintf(stderr, "Styles size diff: %1d\n", Max(newStyleSize, oldStyleSize));
  196.     fprintf(stderr, "fStylePad :%1d\n", theTTECommand->fStylePad);
  197. }
  198.  
  199. #endif
  200.  
  201.  
  202. //========================================================================================
  203. // CLASS TTECommand
  204. //========================================================================================
  205. #undef Inherited
  206. #define Inherited TCommand
  207.  
  208. #pragma segment TESelCommand
  209. MA_DEFINE_CLASS_M1(TTECommand,
  210.                    Inherited);
  211.  
  212. //----------------------------------------------------------------------------------------
  213. // TTECommand constructor
  214. //----------------------------------------------------------------------------------------
  215. #pragma segment TESelCommand
  216.  
  217. TTECommand::TTECommand() :
  218.     fHTE(NULL),
  219.     fNewEnd(0),
  220.     fNewStart(0),
  221.     fNewStyles(NULL),
  222.     fNewText(NULL),
  223.     fOldEnd(0),
  224.     fOldStart(0),
  225.     fOldStyles(NULL),
  226.     fOldText(NULL),
  227.     fOldStaticText(),
  228.     fPadding(NULL),
  229.     fStylePad(0),
  230.     fTEView(NULL),
  231.     fEditText(NULL),
  232.     fTextPad(0)
  233. {
  234. }
  235. // TTECommand::TTECommand
  236.  
  237. //----------------------------------------------------------------------------------------
  238. // TTECommand::ITECommand: 
  239. //----------------------------------------------------------------------------------------
  240. #pragma segment TESelCommand
  241.  
  242. void TTECommand::ITECommand(TTEView* itsTEView,
  243.                             CommandNumber itsCommandNumber,
  244.                             Boolean itsSaveText)
  245. {
  246.     short selChars;
  247.     Handle h;
  248.     TCommandHandler * theContext = NULL;
  249.  
  250.     if (itsTEView)
  251.         theContext = itsTEView->GetContext(itsCommandNumber);
  252.  
  253.     ICommand(itsCommandNumber, theContext, kCanUndo, kCausesChange, theContext);
  254.     fTEView = itsTEView;
  255.     fEditText = itsTEView->GetEditText();
  256.  
  257.     fHTE = itsTEView->fHTE;
  258.  
  259.     {
  260.         TERec & theTERec = **fHTE;
  261.  
  262.         fOldStart = theTERec.selStart;
  263.         fOldEnd = theTERec.selEnd;
  264.         selChars = theTERec.selEnd - theTERec.selStart;
  265.     }
  266.  
  267.     FailInfo fi;
  268.     Try(fi)
  269.     {
  270.         if (itsSaveText)
  271.         {
  272.             h = NewPermHandle(selChars);
  273.  
  274.             if (selChars > 0)
  275.                 MABlockMove((Ptr)((*((*fHTE)->hText)) + fOldStart), (*h), selChars);
  276.  
  277.             fOldText = h;
  278.             fTextPad = fOldStart - fOldEnd;
  279.             fPadding = NewPermHandle(0);
  280.  
  281.             if (fEditText)
  282.                 fEditText->TStaticText::GetText(fOldStaticText);
  283.         }
  284.  
  285.         // TextEdit has this "feature" which it exercises if it runs out of memory. It's
  286.         // called DS number 25. We'll try to avoid it by assuring that enough memory
  287.         // exists to fulfill the request, but we won't die because of it. This is a
  288.         // particularly ugly situation - there could be >600K of style information
  289.         // associated with a 32K block of text. And to support undo, we've got to assume
  290.         // that there may momentarily be THREE copies floating around, adding up to a
  291.         // total potential liability of almost 2 Meg for a single TE record. The worst
  292.         // that can happen, though, is that the text will be safe, but it won't have any
  293.         // styles associated with it.
  294.  
  295.         if ((itsTEView->fStyleType == kWithStyle) && itsTEView->SpaceForStyles((*fHTE)->selStart, (*fHTE)->selEnd))
  296.         {
  297.             Boolean isPermAllocation = PermAllocation(TRUE);
  298.             fOldStyles = TEGetStyleScrapHandle(fHTE);
  299.             PermAllocation(isPermAllocation);
  300.  
  301.             FailNIL(fOldStyles);
  302.  
  303.             fStylePad = GetHandleSize((Handle)fOldStyles);
  304.         }
  305.  
  306.         fi.Success();
  307.     }
  308.     else                                        // Recover
  309.     {
  310.         Free();
  311.         fi.ReSignal();
  312.     }
  313. }
  314.  
  315. //----------------------------------------------------------------------------------------
  316. // TTECommand::ITECommand: 
  317. //----------------------------------------------------------------------------------------
  318. #pragma segment TESelCommand
  319.  
  320. void TTECommand::ITECommand(TEditText* itsEditText,
  321.                             CommandNumber itsCommandNumber,
  322.                             Boolean itsSaveText)
  323. {
  324.     fEditText = itsEditText;
  325.     AssureTEView();
  326.     ITECommand(fTEView, itsCommandNumber, itsSaveText);
  327.     ForgetTEView();
  328. }
  329.  
  330. //----------------------------------------------------------------------------------------
  331. // TTECommand::Free: 
  332. //----------------------------------------------------------------------------------------
  333. #pragma segment TEDoCommand
  334.  
  335. TTECommand::~TTECommand()
  336. {
  337.     fOldText = DisposeIfHandle(fOldText);
  338.     fOldStyles = (StScrpHandle)DisposeIfHandle((Handle)fOldStyles);
  339.     fNewText = DisposeIfHandle(fNewText);
  340.     fNewStyles = (StScrpHandle)DisposeIfHandle((Handle)fNewStyles);
  341.     fPadding = DisposeIfHandle(fPadding);
  342. }
  343.  
  344. //----------------------------------------------------------------------------------------
  345. // TTECommand::AssureTEView: 
  346. //----------------------------------------------------------------------------------------
  347. #pragma segment TEDoCommand
  348.  
  349. void TTECommand::AssureTEView()
  350. {
  351.     if (fEditText)
  352.     {
  353.         if (!fEditText->fTEView)
  354.             fEditText->InstallFloatingTEView(FALSE);
  355.  
  356.         fTEView = fEditText->fTEView;
  357.         fHTE = fTEView->fHTE;
  358.     }
  359. }
  360.  
  361. //----------------------------------------------------------------------------------------
  362. // TTECommand::ForgetTEView: 
  363. //----------------------------------------------------------------------------------------
  364. #pragma segment TEDoCommand
  365.  
  366. void TTECommand::ForgetTEView()
  367. {
  368.     if (fEditText)
  369.     {
  370.         fTEView = NULL;                            // null these references so dependency
  371.         fHTE = NULL;                            // notifications work correctly.
  372.     }
  373. }
  374.  
  375. //----------------------------------------------------------------------------------------
  376. // TTECommand::DoPostProcess
  377. //----------------------------------------------------------------------------------------
  378. #pragma segment TEDoCommand
  379.  
  380. void TTECommand::DoPostProcess()
  381. {
  382.     if (fEditText)
  383.     {
  384.         TWindow * theWindow = fEditText->GetWindow();
  385.         TEventHandler * windowTarget = theWindow ? theWindow->GetWindowTarget() : NULL;
  386.  
  387.         if (!theWindow || (windowTarget != fTEView && windowTarget != fEditText))
  388.         {
  389.             if (!fEditText->IsValid())
  390.                 SetValidationError((OSErr)kInvalidValue);
  391.             fEditText->StopEdit();
  392.         }
  393.         ForgetTEView();
  394.     }
  395. }
  396.  
  397. //----------------------------------------------------------------------------------------
  398. // TTECommand::BanishOldText: 
  399. //----------------------------------------------------------------------------------------
  400. #pragma segment TEDoCommand
  401.  
  402. void TTECommand::BanishOldText()
  403. {
  404.     if (fOldEnd > fOldStart)
  405.         TEDelete(fHTE);
  406.     if (fPadding)
  407.         SetPermHandleSize(fPadding, Max(-(fTextPad + fStylePad), 0));
  408. }
  409.  
  410. //----------------------------------------------------------------------------------------
  411. // TTECommand::InstallNewText: 
  412. //----------------------------------------------------------------------------------------
  413. #pragma segment TEDoCommand
  414.  
  415. void TTECommand::InstallNewText()
  416. {
  417.     long savedSize;
  418.     Handle itsText;
  419.     SignedByte savedState;
  420.  
  421.     if (fNewEnd > fNewStart)
  422.     {
  423.         itsText = fTEView->fText;
  424.         savedSize = GetHandleSize(itsText);
  425.  
  426. #if qDebug
  427.         if (fNewText == NULL)
  428.             ProgramBreak("InstallNewText called with fNewText == NULL!");
  429. #endif
  430.  
  431.         savedState = LockHandleHigh(fNewText);    // Prevent heap fragmentation for TEInsert 
  432.  
  433.         if (fTEView->fStyleType == kWithStyle)    // If record has style, use it 
  434.             TEStyleInsert((*fNewText),            // It's okay for fNewStyles to be NULL here 
  435.                           GetHandleSize(fNewText), fNewStyles, fHTE);
  436.         else                                    // Otherwise, do it the old-fashioned way 
  437.             TEInsert((*fNewText), GetHandleSize(fNewText), fHTE);
  438.  
  439.         HSetState(fNewText, savedState);
  440.  
  441.         if (GetHandleSize(itsText) <= savedSize)
  442.             FailOSErr(memFullErr);
  443.  
  444.         fTEView->fSpecsChanged = TRUE;
  445.     }
  446. }
  447.  
  448. //----------------------------------------------------------------------------------------
  449. // TTECommand::RemoveAdditions: 
  450. //----------------------------------------------------------------------------------------
  451. #pragma segment TEDoCommand
  452.  
  453. void TTECommand::RemoveAdditions()
  454. {
  455.     if (fNewText)
  456.     {
  457.         TESetSelect(fNewStart, fNewEnd, fHTE);
  458.         TEDelete(fHTE);
  459.     }
  460.     if (fPadding)
  461.         SetPermHandleSize(fPadding, Max(fTextPad + fStylePad, 0));
  462. }
  463.  
  464. //----------------------------------------------------------------------------------------
  465. // TTECommand::RestoreSelection: 
  466. //----------------------------------------------------------------------------------------
  467. #pragma segment TEDoCommand
  468.  
  469. void TTECommand::RestoreSelection()
  470. {
  471.     TESetSelect(fOldStart, fOldEnd, fHTE);
  472. }
  473.  
  474. //----------------------------------------------------------------------------------------
  475. // TTECommand::PrepareForUndoRedo:
  476. //----------------------------------------------------------------------------------------
  477. #pragma segment MADoCommand
  478.  
  479. void TTECommand::PrepareForUndoRedo()
  480. {
  481.     if (fEditText)
  482.         fEditText->PrepareForUndoRedo(this);
  483.     else if (fTEView)
  484.         fTEView->PrepareForUndoRedo(this);
  485.     else
  486.         Inherited::PrepareForUndoRedo();
  487. }
  488.  
  489. //----------------------------------------------------------------------------------------
  490. // TTECommand::RevealUndoRedo:
  491. //----------------------------------------------------------------------------------------
  492. #pragma segment MADoCommand
  493.  
  494. void TTECommand::RevealUndoRedo()
  495. {
  496.     if (fEditText)
  497.         fEditText->RevealUndoRedo(this);
  498.     else if (fTEView)
  499.         fTEView->RevealUndoRedo(this);
  500.     else
  501.         Inherited::RevealUndoRedo();
  502. }
  503.  
  504. //----------------------------------------------------------------------------------------
  505. // TTECommand::ReviveDeletions: 
  506. //----------------------------------------------------------------------------------------
  507. #pragma segment TEDoCommand
  508.  
  509. void TTECommand::ReviveDeletions()
  510. {
  511.     Handle itsText;
  512.     long savedSize;
  513.     short nChars;
  514.     SignedByte savedState;
  515.  
  516.  
  517.     TESetSelect(fOldStart, fOldStart, fHTE);    // so insert will take place at right point 
  518.     nChars = (short)GetHandleSize(fOldText);    //!!! long->short
  519.     if (nChars > 0)
  520.     {
  521.         itsText = fTEView->fText;
  522.         savedSize = GetHandleSize(itsText);
  523.  
  524.         savedState = LockHandleHigh(fOldText);    // Prevent heap fragmentation 
  525.  
  526.         if (fTEView->fStyleType == kWithStyle)    // If record has style, use it 
  527.             TEStyleInsert((*fOldText), nChars,    // It's okay for fOldStyles to be NULL here 
  528.                           fOldStyles, fHTE);
  529.         else                                    // Otherwise, do it the old-fashioned way 
  530.             TEInsert((*fOldText), nChars, fHTE);
  531.  
  532.         HSetState(fOldText, savedState);
  533.  
  534.         if (GetHandleSize(itsText) <= savedSize)
  535.             FailOSErr(memFullErr);
  536.  
  537.         fTEView->fSpecsChanged = TRUE;
  538.     }
  539.  
  540.     if (fEditText)
  541.         fEditText->TStaticText::SetText(fOldStaticText, kDontRedraw);
  542. }
  543.  
  544. //----------------------------------------------------------------------------------------
  545. // TTECommand::DoMainFunction: 
  546. //----------------------------------------------------------------------------------------
  547. #pragma segment TEDoCommand
  548.  
  549. void TTECommand::DoMainFunction()
  550. {
  551.     if (fIdentifier != cCopy)
  552.         BanishOldText();
  553.     InstallNewText();
  554.     if (fIdentifier != cCopy)
  555.         fTEView->SynchView(kRedraw);
  556. }
  557.  
  558. //----------------------------------------------------------------------------------------
  559. // TTECommand::SetupDependencies:
  560. //----------------------------------------------------------------------------------------
  561. #pragma segment TEDoCommand
  562.  
  563. void TTECommand::SetupDependencies()
  564. {
  565.     Inherited::SetupDependencies();
  566.  
  567.     if (CanBeUndone())
  568.     {
  569.         if (fEditText)
  570.             fEditText->AddDependent(this);
  571.         else if (fTEView)
  572.             fTEView->AddDependent(this);
  573.     }
  574. }
  575.  
  576. //----------------------------------------------------------------------------------------
  577. // TCommand::DoUpdate:
  578. //----------------------------------------------------------------------------------------
  579. #pragma segment TEDoCommand
  580.  
  581. void TTECommand::DoUpdate(ChangeID theChange,
  582.                           TObject* changedObject,
  583.                           TObject* changedBy,
  584.                           TDependencySpace* dependencySpace)// Override
  585. {
  586.     if ((theChange == mClosed) && ((changedObject == fTEView) || changedObject == fEditText))
  587.         fContext->CommitLastCommand();
  588.     else
  589.         Inherited::DoUpdate(theChange, changedObject, changedBy, dependencySpace);
  590. }
  591.  
  592. //----------------------------------------------------------------------------------------
  593. // TTECommand::DoIt: 
  594. //----------------------------------------------------------------------------------------
  595. #pragma segment TEDoCommand
  596.  
  597. void TTECommand::DoIt()                            // override 
  598. {
  599.     AssureTEView();
  600.     fTEView->Focus();
  601.  
  602.     DoMainFunction();
  603. #if qDebug
  604.     if (TTEView::fgTEIntenseDebugging)
  605.         DumpTTECommand(this);
  606. #endif
  607.  
  608.     DoPostProcess();
  609. }
  610.  
  611. //----------------------------------------------------------------------------------------
  612. // TTECommand::UndoIt: 
  613. //----------------------------------------------------------------------------------------
  614. #pragma segment TEDoCommand
  615.  
  616. void TTECommand::UndoIt()                        // override 
  617. {
  618.     AssureTEView();
  619.     fTEView->Focus();
  620.  
  621.     RemoveAdditions();
  622.     if (fOldText || !fOldStaticText.IsEmpty())
  623.         ReviveDeletions();
  624.     RestoreSelection();
  625.     if (fIdentifier != cCopy)
  626.         fTEView->SynchView(kRedraw);
  627. #if qDebug
  628.     if (TTEView::fgTEIntenseDebugging)
  629.         DumpTTECommand(this);
  630. #endif
  631.  
  632.     DoPostProcess();
  633. }
  634.  
  635. //----------------------------------------------------------------------------------------
  636. // TTECommand::RedoIt: 
  637. //----------------------------------------------------------------------------------------
  638. #pragma segment TEDoCommand
  639.  
  640. void TTECommand::RedoIt()                        // override 
  641. {
  642.     AssureTEView();
  643.     fTEView->Focus();
  644.  
  645.     RestoreSelection();
  646.     DoMainFunction();
  647. #if qDebug
  648.     if (TTEView::fgTEIntenseDebugging)
  649.         DumpTTECommand(this);
  650. #endif
  651.  
  652.     DoPostProcess();
  653. }
  654.  
  655.  
  656. //========================================================================================
  657. // CLASS TTECutCopyCommand
  658. //========================================================================================
  659. #undef Inherited
  660. #define Inherited TTECommand
  661.  
  662. #pragma segment TESelCommand
  663. MA_DEFINE_CLASS_M1(TTECutCopyCommand,
  664.                    Inherited);
  665.  
  666. //----------------------------------------------------------------------------------------
  667. // TTECutCopyCommand::TTECutCopyCommand: Empty constructor to satisfy the compiler.
  668. //----------------------------------------------------------------------------------------
  669. #pragma segment ConstructorRes
  670.  
  671. TTECutCopyCommand::TTECutCopyCommand()
  672. {
  673. }
  674.  
  675. //----------------------------------------------------------------------------------------
  676. // TTECutCopyCommand::ITECutCopyCommand: 
  677. //----------------------------------------------------------------------------------------
  678. #pragma segment TESelCommand
  679.  
  680. void TTECutCopyCommand::ITECutCopyCommand(TTEView* itsTEView,
  681.                                           CommandNumber itsCommandNumber)
  682. {
  683.     fClipCreated = FALSE;
  684.     ITECommand(itsTEView, itsCommandNumber, TRUE);
  685.     fChangesClipboard = TRUE;
  686.     fCausesChange = (itsCommandNumber != cCopy);
  687.     fCanUndo = fCausesChange;
  688. }
  689.  
  690. //----------------------------------------------------------------------------------------
  691. // TTECutCopyCommand::Free: 
  692. //----------------------------------------------------------------------------------------
  693. #pragma segment TEDoCommand
  694.  
  695. TTECutCopyCommand::~TTECutCopyCommand()
  696. {
  697.     if (fClipCreated)
  698.         fOldText = NULL;
  699. }
  700.  
  701. //----------------------------------------------------------------------------------------
  702. // TTECutCopyCommand::DoIt: 
  703. //----------------------------------------------------------------------------------------
  704. #pragma segment TEDoCommand
  705.  
  706. void TTECutCopyCommand::DoIt()                    // override 
  707. {
  708.     //TTECutCopyCommand.DoIt
  709.     TextStyle clipStyle;
  710.     VPoint itsSize;
  711.     VRect itsMargins;
  712.  
  713.     MAVolatile(TTEView * , clipTEView);
  714.  
  715.     fTEView->Focus();
  716.  
  717.     SetTextStyle(clipStyle, applFont, 0, 12, gRGBBlack);// Initial style same as virgin TEView 
  718.  
  719.     itsSize = VPoint(100, 50);                    // An arbitrary initial size.
  720.     itsMargins = VRect(10, 8, 10, 0);            // No bottom margin.
  721.  
  722.     clipTEView = new TTEView;                    // Create a new view for the clipboard 
  723.     clipTEView->ITEView(NULL, NULL,                // Initialize view 
  724.                         gZeroVPt, itsSize, sizeSuperView, sizeVariable, itsMargins, clipStyle, teFlushDefault, fTEView->fStyleType, fTEView->fAutoWrap);
  725.     clipTEView->fAcceptsChanges = FALSE;        // This is a read-only view 
  726.  
  727.     // Cut can eat into temp memory so users can rescue text from overweight documents     
  728.     FailInfo fi;
  729.     Try(fi)
  730.     {
  731.         if (!WillCauseChange())                    // If Copy-ing, assure there's enough room 
  732.             FailSpaceIsLow();
  733.         fi.Success();
  734.     }
  735.     else                                        // Recover
  736.     {
  737.         clipTEView = (TTEView *)(FreeIfObject(clipTEView));
  738.         fi.ReSignal();
  739.     }
  740.  
  741.     clipTEView->StuffText(fOldText);
  742.     FailSpaceIsLow();
  743.  
  744.     if (clipTEView->fStyleType == kWithStyle)    // If record has style 
  745.         TEUseStyleScrap(0, SHRT_MAX, fOldStyles,// …then put in the styles 
  746.                         kDontRedraw, clipTEView->fHTE);
  747.     FailSpaceIsLow();
  748.  
  749.     clipTEView->fFreeText = TRUE;                // Let TEView know it has to free the text 
  750.  
  751.     ClaimClipboard(clipTEView);                    // Okay to claim (will call RecalcText!) 
  752.  
  753.     fClipCreated = TRUE;                        // We be done 
  754.     DoMainFunction();                            // Do the actual cut/copy 
  755.  
  756. #if qDebug
  757.     if (TTEView::fgTEIntenseDebugging)
  758.     {
  759.         TTEView::DumpTERecord(clipTEView->fHTE);
  760.         DumpTTECommand(this);
  761.     }
  762. #endif
  763.  
  764. }
  765.  
  766. //----------------------------------------------------------------------------------------
  767. // TTECutCopyCommand::ReviveDeletions: 
  768. //----------------------------------------------------------------------------------------
  769. #pragma segment TEDoCommand
  770.  
  771. void TTECutCopyCommand::ReviveDeletions()        // override 
  772. {
  773.     if (fIdentifier == cCut)
  774.         Inherited::ReviveDeletions();            // Don't do it for COPY 
  775. }
  776.  
  777.  
  778. //========================================================================================
  779. // CLASS TTEPasteCommand
  780. //========================================================================================
  781. #undef Inherited
  782. #define Inherited TTECommand
  783.  
  784. #pragma segment TESelCommand
  785. MA_DEFINE_CLASS_M1(TTEPasteCommand,
  786.                    Inherited);
  787.  
  788. //----------------------------------------------------------------------------------------
  789. // TTEPasteCommand::TTEPasteCommand: Empty constructor to satisfy the compiler.
  790. //----------------------------------------------------------------------------------------
  791. #pragma segment ConstructorRes
  792.  
  793. TTEPasteCommand::TTEPasteCommand()
  794. {
  795. }
  796.  
  797. //----------------------------------------------------------------------------------------
  798. // TTEPasteCommand destructor
  799. //----------------------------------------------------------------------------------------
  800. #pragma segment MADestructorRes
  801.  
  802. TTEPasteCommand::~TTEPasteCommand()
  803. {
  804. }
  805.  
  806. //----------------------------------------------------------------------------------------
  807. // TTEPasteCommand::ITEPasteCommand: We can't use TEPaste because it clobbers the
  808. // DeskScrap; the text would be recoverable from the special TextEdit Scrap, but other
  809. // types of non-TEXT scrap are permanently lost, it seems
  810. //----------------------------------------------------------------------------------------
  811. #pragma segment TESelCommand
  812.  
  813. void TTEPasteCommand::ITEPasteCommand(TTEView* itsTEView)
  814. {
  815.     ITECommand(itsTEView, cPaste, TRUE);        // Perform stock initializations 
  816.  
  817.     MAVolatileInit(Handle, newText, NULL);
  818.     MAVolatileInit(StScrpHandle, newStyles, NULL);
  819.  
  820.     FailInfo fi;
  821.     Try(fi)
  822.     {
  823.         newText = NewPermHandle(0);                // Create handle to receive clipboard data 
  824.         if (itsTEView->fStyleType == kWithStyle)
  825.             newStyles = (StScrpHandle)NewPermHandle(0);// Same for handle to receive style info 
  826.  
  827.         ResType dataType = '%%%%';
  828.         short newLength = (short)gClipboardMgr->GetDataToPaste(newText, dataType);//!!! long->short
  829.  
  830.         if (newLength > 0)
  831.         {
  832. #if qDebug
  833.             if (dataType != 'TEXT')
  834.                 ProgramBreak("TEPasteCommand given some non-text from clipboard");
  835.             else
  836. #endif
  837.  
  838.                 {                                // Prime "new" values 
  839.                     fNewText = newText;
  840.                     fNewStart = (*fHTE)->selStart;
  841.                     fNewEnd = fNewStart + newLength;
  842.                     fTextPad = newLength - (fOldEnd - fOldStart);
  843.  
  844.                     if (itsTEView->fStyleType == kWithStyle)
  845.                     {
  846.                         long newStyleLen = gClipboardMgr->fClipView->GivePasteData((Handle)newStyles, 'styl');
  847.                         if (newStyleLen > 0)
  848.                         {
  849.                             fNewStyles = newStyles;
  850.                             fStylePad =            // Difference between old and new styles 
  851.                                        newStyleLen - fStylePad;
  852.                         }
  853.                         else
  854.                             newStyles = (StScrpHandle)DisposeIfHandle((Handle)newStyles);
  855.                     }
  856.  
  857.                     if (fPadding)
  858.                         SetPermHandleSize(fPadding, Max(fTextPad + fStylePad, 0));
  859.  
  860.                     FailSpaceIsLow();
  861.                 }
  862.         }
  863.         else
  864.         {
  865.             newText = DisposeIfHandle(newText);
  866.             newStyles = (StScrpHandle)DisposeIfHandle((Handle)newStyles);
  867.         }
  868.  
  869.         if (fEditText)
  870.         {
  871.             CStr255 aString;
  872.             fEditText->GetText(aString);
  873.             fEditText->TStaticText::SetText(aString, kDontRedraw);
  874.         }
  875.         fi.Success();
  876.     }
  877.     else                                        // Recover
  878.     {
  879.         if (newText != fNewText)            // newText is assigned to fNewText 
  880.             newText = DisposeIfHandle(newText);// …so avoid disposing twice. 
  881.         if (newStyles != fNewStyles)        // Ditto for newStyles. 
  882.             newStyles = (StScrpHandle)DisposeIfHandle((Handle)newStyles);
  883.         Free();
  884.         fi.ReSignal();
  885.     }
  886. }
  887.  
  888.  
  889. //========================================================================================
  890. // CLASS TTEStyleCommand
  891. //========================================================================================
  892. #undef Inherited
  893. #define Inherited TTECommand
  894.  
  895. #pragma segment TESelCommand
  896. MA_DEFINE_CLASS_M1(TTEStyleCommand,
  897.                    Inherited);
  898.  
  899. //----------------------------------------------------------------------------------------
  900. // TTEStyleCommand::TTEStyleCommand: Empty constructor to satisfy the compiler.
  901. //----------------------------------------------------------------------------------------
  902. #pragma segment ConstructorRes
  903.  
  904. TTEStyleCommand::TTEStyleCommand()
  905. {
  906. }
  907.  
  908. //----------------------------------------------------------------------------------------
  909. // TTEStyleCommand destructor
  910. //----------------------------------------------------------------------------------------
  911. #pragma segment MADestructorRes
  912.  
  913. TTEStyleCommand::~TTEStyleCommand()
  914. {
  915. }
  916.  
  917. //----------------------------------------------------------------------------------------
  918. // TTEStyleCommand::ITEStyleCommand: 
  919. //----------------------------------------------------------------------------------------
  920. #pragma segment TESelCommand
  921.  
  922. void TTEStyleCommand::ITEStyleCommand(TTEView* itsTEView,
  923.                                       const TextStyle& itsNewStyle,
  924.                                       CommandNumber itsCommandNumber,
  925.                                       short itsMode)
  926. {
  927.     ITECommand(itsTEView, itsCommandNumber, FALSE);// Perform stock initialization, sans text 
  928.  
  929.     fOldTextStyle = itsTEView->fTextStyle;
  930.     fNewTextStyle = itsNewStyle;
  931.  
  932.     // Only do color change if we can 
  933.     if (qNeedsColorQD || HasColorQD())
  934.         fMode = itsMode;
  935.     else
  936.         fMode = itsMode & ~doColor;
  937. }
  938.  
  939. //----------------------------------------------------------------------------------------
  940. // TTEStyleCommand::InstallOneStyle: 
  941. //----------------------------------------------------------------------------------------
  942. #pragma segment TEDoCommand
  943.  
  944. void TTEStyleCommand::InstallOneStyle(const TextStyle& newStyl)
  945. {
  946.     fTEView->SetOneStyle(fOldStart, fOldEnd, fMode, newStyl, kRedraw);// Focus'es for us 
  947. }
  948.  
  949. //----------------------------------------------------------------------------------------
  950. // TTEStyleCommand::InstallManyStyles: 
  951. //----------------------------------------------------------------------------------------
  952. #pragma segment TEDoCommand
  953.  
  954. void TTEStyleCommand::InstallManyStyles(StScrpHandle newStyls)
  955. {
  956.     fTEView->Focus();
  957.     // No need to check for fStyleType, since we only get here if the record is stylish 
  958.     TEUseStyleScrap(fOldStart, fOldEnd, newStyls, kRedraw, fHTE);
  959.  
  960.     if (fOldEnd == fOldStart)
  961.     {
  962.         TextStyle theStyle;
  963.  
  964.         theStyle.tsFont = (*newStyls)->scrpStyleTab[0].scrpFont;
  965.         theStyle.tsFace = (*newStyls)->scrpStyleTab[0].scrpFace;
  966.         theStyle.tsSize = (*newStyls)->scrpStyleTab[0].scrpSize;
  967.         theStyle.tsColor = (*newStyls)->scrpStyleTab[0].scrpColor;
  968.  
  969.         TESetStyle(doAll, &theStyle, kRedraw, fHTE);
  970.     }
  971.  
  972.     fTEView->RecalcText();                        // Might have changed number of lines 
  973.     fTEView->SynchView(kRedraw);                // Show corrected view 
  974.  
  975.     fTEView->fSpecsChanged = TRUE;
  976. }
  977.  
  978. //----------------------------------------------------------------------------------------
  979. // TTEStyleCommand::DoIt: 
  980. //----------------------------------------------------------------------------------------
  981. #pragma segment TEDoCommand
  982.  
  983. void TTEStyleCommand::DoIt()                    // override 
  984. {
  985.     TextStyle aTextStyle;
  986.  
  987.     aTextStyle = fNewTextStyle;
  988.     InstallOneStyle(aTextStyle);
  989.  
  990. #if qDebug
  991.     if (TTEView::fgTEIntenseDebugging)
  992.         DumpTTECommand(this);
  993. #endif
  994.  
  995. }
  996.  
  997. //----------------------------------------------------------------------------------------
  998. // TTEStyleCommand::UndoIt: 
  999. //----------------------------------------------------------------------------------------
  1000. #pragma segment TEDoCommand
  1001.  
  1002. void TTEStyleCommand::UndoIt()                    // override 
  1003. {
  1004.     TextStyle aTextStyle;
  1005.     fTEView->Focus();
  1006.  
  1007.     RestoreSelection();
  1008.  
  1009.     if (fTEView->fStyleType == kWithoutStyle)
  1010.     {
  1011.         aTextStyle = fOldTextStyle;
  1012.         InstallOneStyle(aTextStyle);
  1013.     }
  1014.     else
  1015.         InstallManyStyles(fOldStyles);
  1016. #if qDebug
  1017.     if (TTEView::fgTEIntenseDebugging)
  1018.         DumpTTECommand(this);
  1019. #endif
  1020.  
  1021. }
  1022.  
  1023. //----------------------------------------------------------------------------------------
  1024. // TTEStyleCommand::RedoIt: 
  1025. //----------------------------------------------------------------------------------------
  1026. #pragma segment TEDoCommand
  1027.  
  1028. void TTEStyleCommand::RedoIt()                    // override 
  1029. {
  1030.     fTEView->Focus();
  1031.     RestoreSelection();
  1032.     DoIt();
  1033. }
  1034.  
  1035.  
  1036. //========================================================================================
  1037. // CLASS TTETypingCommand
  1038. //========================================================================================
  1039. #undef Inherited
  1040. #define Inherited TTECommand
  1041.  
  1042. #pragma segment TESelCommand
  1043. MA_DEFINE_CLASS_M1(TTETypingCommand,
  1044.                    Inherited);
  1045.  
  1046. //----------------------------------------------------------------------------------------
  1047. // TTETypingCommand::TTETypingCommand: Empty constructor to satisfy the compiler.
  1048. //----------------------------------------------------------------------------------------
  1049. #pragma segment ConstructorRes
  1050.  
  1051. TTETypingCommand::TTETypingCommand()
  1052. {
  1053. }
  1054.  
  1055. //----------------------------------------------------------------------------------------
  1056. // TTETypingCommand::ITETypingCommand: 
  1057. //----------------------------------------------------------------------------------------
  1058. #pragma segment TERes
  1059.  
  1060. void TTETypingCommand::ITETypingCommand(TTEView* itsTEView,
  1061.                                         const CStr2& itsFirstCh)
  1062. {
  1063.     ITECommand(itsTEView, cTyping, TRUE);
  1064.  
  1065.     FailInfo fi;
  1066.     Try(fi)
  1067.     {
  1068.  
  1069.         fNewStart = (*fHTE)->selStart;            // Start and end are the same 
  1070.         fNewEnd = fNewStart;
  1071.  
  1072.         fNewText = NULL;
  1073.         fNewText = NewPermHandle(0);            // Allocate an empty block for text 
  1074.  
  1075.         fCompleted = FALSE;                        // We've only just begun… 
  1076.         fFirstChar = itsFirstCh;                // Save character[s] for Doit 
  1077.         fi.Success();
  1078.     }
  1079.     else                                        // Recover
  1080.     {
  1081.         Free();
  1082.         fi.ReSignal();
  1083.     }
  1084. }
  1085.  
  1086. //----------------------------------------------------------------------------------------
  1087. // TTETypingCommand::Free: 
  1088. //----------------------------------------------------------------------------------------
  1089. #pragma segment TERes
  1090.  
  1091. TTETypingCommand::~TTETypingCommand()
  1092. {
  1093.     if (fTEView->fTypingCommand == this)
  1094.         fTEView->fTypingCommand = NULL;
  1095. }
  1096.  
  1097. //----------------------------------------------------------------------------------------
  1098. // TTETypingCommand::DoNormalChar: 
  1099. //----------------------------------------------------------------------------------------
  1100. #pragma segment TERes
  1101.  
  1102. void TTETypingCommand::DoNormalChar(const CStr2& ch)
  1103. {
  1104.     // Append char[s] to end of fNewText
  1105.  
  1106.     Boolean oldPerm = PermAllocation(TRUE);
  1107.     FailOSErr(PtrAndHand((Ptr) & ch[1], fNewText, ch.Length()));
  1108.     PermAllocation(oldPerm);
  1109.  
  1110.     fNewEnd += ch.Length();                        // Bump both end of "selection" 
  1111.     fTextPad += ch.Length();                    // …and padding value 
  1112.  
  1113.     // This SetPermHandleSize can't grow the handle,
  1114.     if (fPadding)
  1115.         SetPermHandleSize(fPadding, Max(-(fTextPad + fStylePad), 0));// …so it shouldn't fail. 
  1116. }
  1117.  
  1118. //----------------------------------------------------------------------------------------
  1119. // TTETypingCommand::BkSpcLeft: User has backspaced to the left of the original starting
  1120. // point. First, copy the character (which may be more than one byte long if we are using
  1121. // a non-Roman script) to a temporary buffer. The assumption is that no character will
  1122. // ever be longer than four bytes. Sorry, folks, MacApp does not support typing in any
  1123. // script with more than 4 billion characters. Next, copy the character to the front of
  1124. // fOldText, and adjust fOldStart, fNewStart, and fNewEnd. Note that we do !check for
  1125. // MemSpaceIsLow, since we want to let the user delete characters.
  1126. //----------------------------------------------------------------------------------------
  1127. #pragma segment TERes
  1128.  
  1129. void TTETypingCommand::BkSpcLeft(Handle theText,
  1130.                                  short curStart)
  1131. {
  1132.     unsigned char saveLength = 1;
  1133.     if (MACharacterByteType((*theText), curStart - 1, smCurrentScript) == smLastByte)
  1134.         saveLength++;
  1135.     curStart -= saveLength;
  1136.  
  1137.     CStr2 savedCh;
  1138.     savedCh.CopyFrom((void*)((*theText) + curStart), saveLength);
  1139.  
  1140.     if (fTEView->fStyleType == kWithStyle)        // Only do this if styles are around 
  1141.     {
  1142.         TextStyle delStyle;
  1143.         short theHeight;
  1144.         short theAscent;
  1145.         TEGetStyle(curStart, &delStyle,            // Get the style of the deleted character 
  1146.                    &theHeight, &theAscent, fHTE);// (1 or 4 bytes, it's all only one style) 
  1147.  
  1148.         if (!EqualBlocks((Ptr) & delStyle,        // If style doesn't match first in the list 
  1149.                          (Ptr) & ((*fOldStyles)->scrpStyleTab[0].scrpFont), sizeof(TextStyle)))
  1150.         {
  1151.             // …then insert new style at head of list 
  1152.             fTEView->fSpecsChanged = TRUE;        // User backspaced into new style! 
  1153.  
  1154.             long oldSize =                        // Make room for the new style element 
  1155.                           GetHandleSize((Handle)fOldStyles);
  1156.             SetPermHandleSize((Handle)fOldStyles, oldSize + sizeof(ScrpSTElement));
  1157.             fStylePad += sizeof(ScrpSTElement);
  1158.  
  1159.             {
  1160.                 //ScrpSTElement & theScrpSTElement = (*fOldStyles)->scrpStyleTab[0];
  1161.                 ScrpSTElement * theScrpSTElement = &(*fOldStyles)->scrpStyleTab[0];
  1162.  
  1163.                 //    MABlockMove(&(theScrpSTElement.scrpStartChar),// Move entire array up one element's size 
  1164.                 //                (Ptr)&(theScrpSTElement.scrpStartChar) + sizeof(ScrpSTElement),
  1165.                 //                oldSize - sizeof((*fOldStyles)->scrpNStyles));
  1166.                 MABlockMove(theScrpSTElement, (Ptr)theScrpSTElement + sizeof(ScrpSTElement), oldSize - sizeof(ScrpSTElement));
  1167.             }
  1168.  
  1169.             (*fOldStyles)->scrpNStyles++;        // One more style 
  1170.  
  1171.             {
  1172.                 ScrpSTElement & theScrpSTElement = (*fOldStyles)->scrpStyleTab[0];
  1173.  
  1174.                 theScrpSTElement.scrpHeight = theHeight;// Fill in the blanks 
  1175.                 theScrpSTElement.scrpAscent = theAscent;
  1176.                 MABlockMove(&delStyle, &theScrpSTElement.scrpFont, sizeof(TextStyle));
  1177.             }
  1178.         }
  1179.  
  1180.         (*fOldStyles)->scrpStyleTab[0].scrpStartChar--;// Regardless, back off offset by one 
  1181.     }
  1182.  
  1183.     if (fPadding)
  1184.         SetPermHandleSize(fPadding, GetHandleSize(fOldText) + savedCh.Length() + fStylePad);
  1185.     Munger(fOldText, 0, NULL, 0, &savedCh[1], savedCh.Length());
  1186.     FailMemError();
  1187.     fOldStart = curStart;                        // Treat this as though original selection 
  1188.     fNewStart = curStart;                        // …had included this character 
  1189.     fNewEnd = curStart;
  1190.     fTextPad -= savedCh.Length();
  1191. }
  1192.  
  1193. //----------------------------------------------------------------------------------------
  1194. // TTETypingCommand::BkSpcRight: 
  1195. //----------------------------------------------------------------------------------------
  1196. #pragma segment TERes
  1197.  
  1198. void TTETypingCommand::BkSpcRight(Handle theText,
  1199.                                   short curStart)
  1200. {
  1201.     short savedSize = 1;
  1202.     if (MACharacterByteType((*theText), curStart - savedSize, smCurrentScript) == smLastByte)
  1203.         ++savedSize;
  1204.     if (fPadding)
  1205.         SetPermHandleSize(fPadding, Max(-(fTextPad - savedSize + fStylePad), 0));
  1206.     fNewEnd -= savedSize;
  1207.     fTextPad -= savedSize;
  1208.  
  1209.     SetPermHandleSize(fNewText, fNewEnd - fNewStart);// Shouldn't fail as we're only shrinking it
  1210. }
  1211.  
  1212. //----------------------------------------------------------------------------------------
  1213. // TTETypingCommand::FwdDelete: Forward delete courtesy of: Larry Goldman. Used by
  1214. // permission.
  1215. //----------------------------------------------------------------------------------------
  1216. #pragma segment TERes
  1217.  
  1218. void TTETypingCommand::FwdDelete(Handle theText,
  1219.                                  short curStart,
  1220.                                  short curEnd)
  1221. {
  1222.     short theHeight;
  1223.     short theAscent;
  1224.     long oldSize;
  1225.     TextStyle delStyle;
  1226.     long oldTextSize;
  1227.  
  1228.     CStr2 savedCh;
  1229.  
  1230.     long textSize = GetHandleSize(theText);
  1231.     if ((curStart == curEnd) && (curStart < textSize))
  1232.     {
  1233.         unsigned char saveLength = 0;            //Get the complete character
  1234.         if ((curStart + saveLength <= textSize) && (MACharacterByteType((*theText), curStart + saveLength, smCurrentScript) == smLastByte))
  1235.             ++saveLength;
  1236.         ++saveLength;
  1237.  
  1238.         savedCh.CopyFrom((void*)((*theText) + curStart), saveLength);
  1239.  
  1240.         if ((curStart >= fNewStart) && (curStart < fNewEnd))// char is within fNewText 
  1241.         {
  1242.             // Remove the char from fNewText and update fNewEnd and fTextPad
  1243.             if (fPadding)
  1244.                 SetPermHandleSize(fPadding, Max(-(fTextPad - savedCh.Length() + fStylePad), 0));
  1245.             fNewEnd -= savedCh.Length();
  1246.             fTextPad -= savedCh.Length();
  1247.  
  1248.             // Shouldn't fail as we're only shrinking it 
  1249.             Munger(fNewText, curStart - fNewStart, NULL, savedCh.Length(), &savedCh[1], 0);
  1250.             FailMemError();
  1251.         }
  1252.         else                                    // add char to the end of fOldChars, don't
  1253.             // update fOldEnd, but update fPadding
  1254.             {
  1255.                 oldTextSize = GetHandleSize(fOldText);
  1256.                 if (fTEView->fStyleType == kWithStyle)// Only do this if styles are around 
  1257.                 {
  1258.                     TEGetStyle(curStart, &delStyle,// Get the style of the deleted character 
  1259.                                &theHeight, &theAscent, fHTE);// (1 or 4 bytes, it's all only one style) 
  1260.  
  1261.                     if (!EqualBlocks((Ptr) & delStyle,// If style doesn't match last in the list 
  1262.                                      (Ptr) & (*fOldStyles)->scrpStyleTab[(*fOldStyles)->scrpNStyles - 1].scrpFont, sizeof(TextStyle)))
  1263.                     {
  1264.                         // …then insert new style at end of list 
  1265.                         fTEView->fSpecsChanged = TRUE;// User backspaced into new style! 
  1266.  
  1267.                         oldSize = GetHandleSize((Handle)fOldStyles);// Make room for the new style element 
  1268.                         SetPermHandleSize((Handle)fOldStyles, oldSize + sizeof(ScrpSTElement));
  1269.                         fStylePad += sizeof(ScrpSTElement);
  1270.  
  1271.                         (*fOldStyles)->scrpNStyles++;// One more style 
  1272.  
  1273.                         {
  1274.                             ScrpSTElement & theScrpSTElement = (*fOldStyles)->scrpStyleTab[(*fOldStyles)->scrpNStyles - 1];
  1275.  
  1276.                             theScrpSTElement.scrpStartChar = oldTextSize;
  1277.                             theScrpSTElement.scrpHeight = theHeight;// Fill in the blanks 
  1278.                             theScrpSTElement.scrpAscent = theAscent;
  1279.                             MABlockMove(&delStyle, &theScrpSTElement.scrpFont, sizeof(TextStyle));
  1280.                         }
  1281.                     }
  1282.                 }
  1283.  
  1284.                 if (fPadding)
  1285.                     SetPermHandleSize(fPadding, oldTextSize + savedCh.Length() + fStylePad);
  1286.                 Munger(fOldText, oldTextSize, NULL, 0, &savedCh[1], savedCh.Length());
  1287.                 FailMemError();
  1288.                 fTextPad = fTextPad - savedCh.Length();
  1289.             }
  1290.     }
  1291. }
  1292.  
  1293. //----------------------------------------------------------------------------------------
  1294. // TTETypingCommand::AddCharacter: 
  1295. //----------------------------------------------------------------------------------------
  1296. #pragma segment TERes
  1297.  
  1298. void TTETypingCommand::AddCharacter(const CStr2& ch)
  1299. {
  1300.     Handle theText;
  1301.     short curSelStart;
  1302.     short curSelEnd;
  1303.     MAVolatile(Boolean, savedPerm);
  1304.  
  1305.     fTEView->Update();                            // Makes sure that all of TE's actions are Visible
  1306.     fTEView->Focus();
  1307.  
  1308.     {
  1309.         TERec & theTERec = **fHTE;
  1310.  
  1311.         curSelStart = theTERec.selStart;
  1312.         curSelEnd = theTERec.selEnd;
  1313.         theText = theTERec.hText;
  1314.     }
  1315.  
  1316.     CWhileOutlinePreferred setOP(fTEView->fPreferOutline);
  1317.  
  1318.     FailInfo fi;
  1319.     Try(fi)
  1320.     {
  1321.         savedPerm = PermAllocation(TRUE);
  1322.  
  1323.         // Update the fNewText handle and other information. Note that because of
  1324.         // backspace, this can be tricky.*/
  1325.         if (ch == chFwdDelete)                    // User types forward delete, so keep in  synch
  1326.             FwdDelete(theText, curSelStart, curSelEnd);
  1327.  
  1328.         else if (ch != chBackspace)                // Not a backspace. Do the right thing 
  1329.             DoNormalChar(ch);
  1330.  
  1331.         else if ((curSelStart <= fOldStart) && (curSelStart > 0) && (curSelStart == curSelEnd))// User typed backspace so keep in synch 
  1332.             BkSpcLeft(theText, curSelStart);    // Handle backspace to left of start 
  1333.  
  1334.         else if (fNewEnd > fNewStart)            // Delete 1 character from end of fNewText 
  1335.             BkSpcRight(theText, curSelStart);    // Handle backspace to right of start 
  1336.  
  1337.         savedPerm = PermAllocation(savedPerm);
  1338.         fi.Success();
  1339.     }
  1340.     else                                        // Recover
  1341.     {
  1342.         savedPerm = PermAllocation(savedPerm);
  1343.         fi.ReSignal();
  1344.     }
  1345.  
  1346.     if (ch != chFwdDelete)
  1347.     {
  1348.         // Let TextEdit have the character, as either 1) we're adding a byte, so we know
  1349.         // there is a reserve tank, so the worst this will do is eat into it a little, or
  1350.         // 2) we're deleting a character, which can only decrease memory usage.
  1351.  
  1352.         // NOTE: here is where we insert multibyte characters all at once
  1353.         TEKey(ch[1], fHTE);
  1354.         if (ch.Length() > 1)
  1355.             TEKey(ch[2], fHTE);
  1356.     }
  1357.     else if (curSelStart != curSelEnd)            // forward delete with chars selected
  1358.         TEDelete(fHTE);
  1359.     else if (curSelStart < GetHandleSize(theText))
  1360.     {
  1361.         // forward delete with insertion point
  1362.         TEKey(chRight, fHTE);
  1363.         TEKey(chBackspace, fHTE);
  1364.     }
  1365.  
  1366.     fTEView->SynchView(kRedraw);                // Now clean up the view. 
  1367.  
  1368. #if qDebugMsg
  1369.     if (TTEView::fgTEIntenseDebugging)
  1370.     {
  1371.         WrLblHandleContents("fOldText", fOldText);
  1372.         fprintf(stderr, "\n");
  1373.         WrLblHandleContents("fNewText", fNewText);
  1374.         fprintf(stderr, "\n");
  1375.         DumpTTECommand(this);
  1376.     }
  1377. #endif
  1378.  
  1379. }
  1380.  
  1381. //----------------------------------------------------------------------------------------
  1382. // TTETypingCommand::DoIt: 
  1383. //----------------------------------------------------------------------------------------
  1384. #pragma segment TERes
  1385.  
  1386. void TTETypingCommand::DoIt()                    // override 
  1387.  
  1388. {
  1389.     AddCharacter(fFirstChar);
  1390. #if qDebug
  1391.     if (TTEView::fgTEIntenseDebugging)
  1392.         DumpTTECommand(this);
  1393. #endif
  1394.  
  1395. }
  1396.  
  1397. //----------------------------------------------------------------------------------------
  1398. // TTETypingCommand::RedoIt: 
  1399. //----------------------------------------------------------------------------------------
  1400. #pragma segment TEDoCommand
  1401.  
  1402. void TTETypingCommand::RedoIt()                    // override 
  1403.  
  1404. {
  1405.     TextStyle currentStyle;
  1406.     short lineHeight;
  1407.     short fontAscent;
  1408.     Boolean resetStyle;
  1409.  
  1410.     if ((fOldEnd - fOldStart) == GetHandleSize(fOldText))
  1411.     {
  1412.         // No chars were vacuumed
  1413.         resetStyle = FALSE;
  1414.         if ((fTEView->fStyleType == kWithStyle) && (fOldEnd == fOldStart))
  1415.         {
  1416.             TEGetStyle(fOldStart, ¤tStyle, &lineHeight, &fontAscent, fHTE);
  1417.             resetStyle = !EqualBlocks((Ptr) & currentStyle, (Ptr) & (*fOldStyles)->scrpStyleTab[0].scrpFont, sizeof(TextStyle));
  1418.         }
  1419.  
  1420.         if (resetStyle)                            // The new text has a style of its own 
  1421.             fNewStyles = fOldStyles;            // Make InstallNewText insert styles, too 
  1422.         Inherited::RedoIt();
  1423.         if (resetStyle)
  1424.             fNewStyles = NULL;                    // So fNewStyles doesn't get disposed 
  1425.     }
  1426.     else
  1427.     {
  1428.         fTEView->Focus();
  1429.         TESetSelect(fOldStart, fOldStart + GetHandleSize(fOldText), fHTE);// select
  1430.         // vacuumed
  1431.         // chars, too
  1432.         TEDelete(fHTE);                            // Remove old text, including vacuumed chars
  1433.         if (fPadding)
  1434.             SetPermHandleSize(fPadding, Max(-(fTextPad + fStylePad), 0));
  1435.         InstallNewText();
  1436.         fTEView->SynchView(kRedraw);
  1437. #if qDebug
  1438.         if (TTEView::fgTEIntenseDebugging)
  1439.             DumpTTECommand(this);
  1440. #endif
  1441.  
  1442.     }
  1443. }
  1444.  
  1445. //----------------------------------------------------------------------------------------
  1446. // TTETypingCommand::UndoIt: 
  1447. //----------------------------------------------------------------------------------------
  1448. #pragma segment TEDoCommand
  1449.  
  1450. void TTETypingCommand::UndoIt()                    // override 
  1451. {
  1452.     CompleteTyping();
  1453.     Inherited::UndoIt();
  1454. }
  1455.  
  1456. //----------------------------------------------------------------------------------------
  1457. // TTETypingCommand::CompleteTyping: 
  1458. //----------------------------------------------------------------------------------------
  1459. #pragma segment TERes
  1460.  
  1461. void TTETypingCommand::CompleteTyping()
  1462. {
  1463.     fCompleted = TRUE;
  1464.  
  1465.     if (fTEView->fStyleType == kWithStyle)
  1466.     {
  1467.         StScrpRec & theStScrpRec = **fOldStyles;
  1468.         long offset = -theStScrpRec.scrpStyleTab[0].scrpStartChar;
  1469.         if (offset > 0)
  1470.             for (short i = 0; i <= theStScrpRec.scrpNStyles - 1; ++i)
  1471.                 theStScrpRec.scrpStyleTab[i].scrpStartChar += offset;
  1472.     }
  1473. #if qDebug
  1474.     if (TTEView::fgTEIntenseDebugging)
  1475.         DumpTTECommand(this);
  1476. #endif
  1477.  
  1478. }
  1479.  
  1480. #if qDrag
  1481.  
  1482. //========================================================================================
  1483. // CLASS TTEDragDropCommand
  1484. //========================================================================================
  1485. #undef Inherited
  1486. #define Inherited TTECommand
  1487.  
  1488. #pragma segment MADragNonRes
  1489. MA_DEFINE_CLASS_M1(TTEDragDropCommand,
  1490.                    Inherited);
  1491.  
  1492. //----------------------------------------------------------------------------------------
  1493. // TTEDragDropCommand::TTEDragDropCommand: 
  1494. //----------------------------------------------------------------------------------------
  1495. #pragma segment MADragNonRes
  1496.  
  1497. TTEDragDropCommand::TTEDragDropCommand()
  1498. {
  1499.     fNewStyles = NULL;
  1500. }
  1501.  
  1502. //----------------------------------------------------------------------------------------
  1503. // TTEDragDropCommand destructor
  1504. //----------------------------------------------------------------------------------------
  1505. #pragma segment MADestructorRes
  1506.  
  1507. TTEDragDropCommand::~TTEDragDropCommand()
  1508. {
  1509. }
  1510.  
  1511. //----------------------------------------------------------------------------------------
  1512. // TTEDragDropCommand::ITEDragDropCommand: 
  1513. //----------------------------------------------------------------------------------------
  1514. #pragma segment MADragNonRes
  1515.  
  1516. void TTEDragDropCommand::ITEDragDropCommand(TTEView* itsTEView,
  1517.                                             CommandNumber itsCommandNumber)
  1518. {
  1519.     ITECommand(itsTEView, itsCommandNumber, FALSE);
  1520. }
  1521.  
  1522. //----------------------------------------------------------------------------------------
  1523. // TTEDragDropCommand::ITEDragDropCommand: 
  1524. //----------------------------------------------------------------------------------------
  1525. #pragma segment MADragNonRes
  1526.  
  1527. void TTEDragDropCommand::ITEDragDropCommand(TEditText* itsEditText,
  1528.                                             CommandNumber itsCommandNumber)
  1529. {
  1530.     ITECommand(itsEditText, itsCommandNumber, FALSE);
  1531. }
  1532.  
  1533. //----------------------------------------------------------------------------------------
  1534. // TTEDragDropCommand::DoMainFunction: 
  1535. //----------------------------------------------------------------------------------------
  1536. #pragma segment MADragNonRes
  1537.  
  1538. void TTEDragDropCommand::DoMainFunction()
  1539. {
  1540.     InstallNewText();
  1541.     fTEView->SynchView(kRedraw);
  1542. }
  1543.  
  1544. //----------------------------------------------------------------------------------------
  1545. // TTEDragDropCommand::SetNewText: 
  1546. //----------------------------------------------------------------------------------------
  1547. #pragma segment MADragNonRes
  1548.  
  1549. void TTEDragDropCommand::SetNewText(Handle newText,
  1550.                                     StScrpHandle newStyles)
  1551. {
  1552.     fNewText = newText;
  1553.     fNewEnd = fNewStart + (short)GetHandleSize(newText);// correct for text size
  1554.     fNewStyles = newStyles;
  1555. }
  1556.  
  1557. //----------------------------------------------------------------------------------------
  1558. // TTEDragDropCommand::SetNewStart: 
  1559. //----------------------------------------------------------------------------------------
  1560. #pragma segment MADragNonRes
  1561.  
  1562. void TTEDragDropCommand::SetNewStart(short newStart)
  1563. {
  1564.     short textSize = fNewEnd - fNewStart;
  1565.     fNewStart = newStart;
  1566.     fNewEnd = fNewStart + textSize;
  1567. }
  1568.  
  1569. //----------------------------------------------------------------------------------------
  1570. // TTEDragDropCommand::InstallNewText: 
  1571. //----------------------------------------------------------------------------------------
  1572. #pragma segment MADragNonRes
  1573.  
  1574. void TTEDragDropCommand::InstallNewText()
  1575. {
  1576.     VRect textEditArea(fTEView->GetExtent());
  1577.     fTEView->SetSelection(fNewStart, fNewStart, kRedraw);
  1578.     fTEView->Draw(textEditArea);
  1579.     Inherited::InstallNewText();
  1580.     // fTEView->SetSelection(fNewStart, fNewEnd, kRedraw);
  1581.     fTEView->Draw(textEditArea);
  1582. }
  1583.  
  1584. //========================================================================================
  1585. // CLASS TTEDragMoveCommand
  1586. //========================================================================================
  1587. #undef Inherited
  1588. #define Inherited TTECommand
  1589.  
  1590. #pragma segment MADragNonRes
  1591. MA_DEFINE_CLASS_M1(TTEDragMoveCommand,
  1592.                    Inherited);
  1593.  
  1594. //----------------------------------------------------------------------------------------
  1595. // TTEDragMoveCommand::TTEDragMoveCommand: 
  1596. //----------------------------------------------------------------------------------------
  1597. #pragma segment MADragNonRes
  1598.  
  1599. TTEDragMoveCommand::TTEDragMoveCommand()
  1600. {
  1601.  
  1602. }
  1603.  
  1604. //----------------------------------------------------------------------------------------
  1605. // TTEDragMoveCommand::Free: 
  1606. //----------------------------------------------------------------------------------------
  1607. TTEDragMoveCommand::~TTEDragMoveCommand()
  1608. {
  1609.     // fNewText and fOldText share a handle in this command. fNewText is NULLed to
  1610.     // prevent double disposal in the inherited Free().
  1611.     fNewText = NULL;
  1612.     fNewStyles = NULL;
  1613. }
  1614.  
  1615. //----------------------------------------------------------------------------------------
  1616. // TTEDragMoveCommand::ITEDragMoveCommand: 
  1617. //----------------------------------------------------------------------------------------
  1618. #pragma segment MADragNonRes
  1619.  
  1620. void TTEDragMoveCommand::ITEDragMoveCommand(TTEView* itsTEView,
  1621.                                             CommandNumber itsCommandNumber,
  1622.                                             short newStart)
  1623. {
  1624.     // initialize the command, and save the selection into fOldText
  1625.     ITECommand(itsTEView, itsCommandNumber, TRUE);
  1626.  
  1627.     // fOldStart and fOldEnd represent the text being dragged
  1628.     // fNewStart takes its impending relocation into account
  1629.     fNewStart = (fOldStart < newStart) ? (newStart - (fOldEnd - fOldStart)) : newStart;
  1630.     fNewEnd = fNewStart + (fOldEnd - fOldStart);
  1631.  
  1632.     // since new and old text are the same, the text handle can be shared
  1633.     fNewText = fOldText;
  1634.     fNewStyles = fOldStyles;
  1635. }
  1636.  
  1637. //----------------------------------------------------------------------------------------
  1638. // TTEDragMoveCommand::ITEDragMoveCommand: 
  1639. //----------------------------------------------------------------------------------------
  1640. #pragma segment MADragNonRes
  1641.  
  1642. void TTEDragMoveCommand::ITEDragMoveCommand(TEditText* itsEditText,
  1643.                                             CommandNumber itsCommandNumber,
  1644.                                             short newStart)
  1645. {
  1646.     // initialize the command, and save the selection into fOldText
  1647.     ITECommand(itsEditText, itsCommandNumber, TRUE);
  1648.  
  1649.     // fOldStart and fOldEnd represent the text being dragged
  1650.     // fNewStart takes its impending relocation into account
  1651.     fNewStart = (fOldStart < newStart) ? (newStart - (fOldEnd - fOldStart)) : newStart;
  1652.     fNewEnd = fNewStart + (fOldEnd - fOldStart);
  1653.  
  1654.     // since new and old text are the same, the text handle can be shared
  1655.     fNewText = fOldText;
  1656.     fNewStyles = fOldStyles;
  1657. }
  1658.  
  1659. //----------------------------------------------------------------------------------------
  1660. // TTEDragMoveCommand::InstallNewText: 
  1661. //----------------------------------------------------------------------------------------
  1662. #pragma segment MADragNonRes
  1663.  
  1664. void TTEDragMoveCommand::InstallNewText()
  1665. {
  1666.     // set the text insertion point
  1667.     TESetSelect(fNewStart, fNewStart, fHTE);
  1668.  
  1669.     Inherited::InstallNewText();
  1670.  
  1671.     TESetSelect(fNewStart, fNewEnd, fHTE);
  1672. }
  1673.  
  1674. #endif // qDrag
  1675.  
  1676. //----------------------------------------------------------------------------------------
  1677. // End of UTECommands.cp
  1678.  
  1679. #pragma segment Inline
  1680.  
  1681.